﻿namespace EFS.RC.CC.Sessions.OfficeService
{
	/// <summary>
	/// Customer session
	/// </summary>
	internal abstract class Participant : EFS.Common.Async.AsyncRoot, EFS.RC.CC.Sessions.OfficeService.IParticipant
	{
		#region Composition

		// sync access
		protected object syncAccess = new object();

		// Participat end point
		private Microsoft.Rtc.Collaboration.ParticipantEndpoint participantEndPoint = null;

		#endregion

		#region Delgates

		/// <summary>
		/// Established delegate
		/// </summary>
		public EFS.Common.Async.AsyncDelegate<EFS.RC.CC.Sessions.OfficeService.IParticipant> AsinkEstablishedDelegate { get; private set; }

		/// <summary>
		/// Terminate delegate
		/// </summary>
		public EFS.Common.Async.AsyncDelegate<EFS.RC.CC.Sessions.OfficeService.IParticipant> AsinkTerminatedDelegate { get; private set; }

		#endregion

		#region Constructor

		/// <summary>
		/// Constructor
		/// </summary>
		public Participant()
		{
			// delegate
			AsinkTerminatedDelegate = new EFS.Common.Async.AsyncDelegate<IParticipant>(this);
			AsinkEstablishedDelegate = new EFS.Common.Async.AsyncDelegate<IParticipant>(this);
		}

		#endregion

		#region Usage

		/// <summary>
		/// Office service conference
		/// </summary>
		public abstract EFS.RC.CC.Confereces.OfficeService OfficeServiceConference { get; }

		/// <summary>
		/// Participant end point URI
		/// </summary>
		public abstract System.String ParticipantEndPointUri { get; }

		/// <summary>
		/// Get participant remote end point
		/// </summary>
		public virtual Microsoft.Rtc.Collaboration.ParticipantEndpoint ParticipantRemoteEndPoint
		{
			get
			{
				// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
				lock (syncAccess)
				{
					// is here
					return ParticipantEndPoint;
				}
			}
		}

		/// <summary>
		/// Get participant end point
		/// </summary>
		public Microsoft.Rtc.Collaboration.ParticipantEndpoint ParticipantEndPoint
		{
			get
			{
				// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
				lock (syncAccess)
				{
					// check
					EFS.Common.Verify.Reference(participantEndPoint, "participantEndPoint");

					// is here
					return participantEndPoint;
				}
			}
		}

		/// <summary>
		/// Begin startup
		/// </summary>
		public abstract EFS.Common.Async.AsyncProcess BeginStartup();

		/// <summary>
		/// Begin shutdows
		/// </summary>
		public abstract EFS.Common.Async.AsyncProcess BeginShutdown();

		/// <summary>
		/// Handle added end point in conference
		/// </summary>
		/// <param name="conversationParticipantEndPoint"></param>
		public void HandleParticipantEndPointAdded(Microsoft.Rtc.Collaboration.ParticipantEndpoint participantEndPoint)
		{
			// check
			EFS.Common.Verify.Reference(participantEndPoint, "participantEndPoint");

			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// is here
				if (null != this.participantEndPoint)
				{
					throw new System.InvalidOperationException("Participat End Point already set.");
				}

				// set
				this.participantEndPoint = participantEndPoint;

				// init tone
				BeginAsyncProcess2(ParticipantEndPointAdded);
			}
		}

		/// <summary>
		/// Handle removed end point in conversation
		/// </summary>
		/// <param name="conversationParticipantEndPoint"></param>
		public void HandleParticipantEndPointRemoved(Microsoft.Rtc.Collaboration.ParticipantEndpoint participantEndPoint)
		{
			// check
			EFS.Common.Verify.Reference(participantEndPoint, "participantEndPoint");

			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// is here
				if (null == this.participantEndPoint)
				{
					throw new System.InvalidOperationException("Participat End Point not set.");
				}

				// check correct url
				if (!EFS.RC.Common.Utilities.SipUriCompare(ParticipantEndPointUri, participantEndPoint.Participant.Uri))
				{
					throw new System.InvalidOperationException("Participat End Point Uri is different");
				}

				// set
				this.participantEndPoint = null;

				// shut down
				BeginAsyncProcess2(ParticipantEndPointRemoved);
			}
		}

		#endregion

		#region Runtime

		/// <summary>
		/// Called when participant end point added
		/// </summary>
		protected abstract void ParticipantEndPointAdded();

		/// <summary>
		/// Called when participant end point removed
		/// </summary>
		protected abstract void ParticipantEndPointRemoved();


		#endregion

	}
}
